package com.edu.modules.baseinfo.api;

import com.alibaba.fastjson.JSONObject;
import com.sari.common.utils.FileUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author wangsf
 * @version 2018-04-24
 */
@CrossOrigin(origins = "*", maxAge = 3600)
@Controller
@RequestMapping(value = "fileUpload")
public class FileUploadApi {

    private static Logger logger = LoggerFactory.getLogger(FileUploadApi.class);

    @ResponseBody
    @RequestMapping(value = "/service",method = {RequestMethod.POST,RequestMethod.GET})
    public JSONObject service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

        if(request.getMethod().equals("GET")){
            doGet(request, response);
        }else if(request.getMethod().equals("POST")){
            doPost(request, response);
        }
        return null;
    }

    static String docStorePath;
    static File docStoreDir;

    static{
        String baasPath = Thread.currentThread().getContextClassLoader().getResource("").getPath() + ".." + File.separator + ".." + File.separator + "..";
        docStorePath = baasPath + File.separator + "homework";
        File file = new File(docStorePath);
        if(!(file.exists() && file.isDirectory())){
            file.mkdirs();
        }
        docStoreDir = file;
    }



    /**
     get为获取文件 浏览或者下载
     **/
    private void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String operateType = request.getParameter("operateType");
        if("copy".equals(operateType)){
            copyFile(request,response);
        }else{
            getFile(request,response);
        }
    }


    private void copyFile(HttpServletRequest request,
                                 HttpServletResponse response) throws IOException {

        String storeFileName = request.getParameter("storeFileName");
        File file = new File(docStorePath + File.separator + storeFileName);
        File targetFile = new File(docStorePath + File.separator + storeFileName);
        FileUtils.copyFile(file, targetFile);
    }


    private static final int BUFFER_SIZE = 32768 * 8;
    private void getFile(HttpServletRequest request,
                                HttpServletResponse response) throws IOException {

        String realFileName = URLEncoder.encode(request.getParameter("realFileName"),"utf-8");
        String storeFileName = request.getParameter("storeFileName");
        String operateType = request.getParameter("operateType");
		/*String fileSize = request.getParameter("fileSize");*/

        File file = new File(docStorePath + File.separator + storeFileName);
        FileInputStream fis = new FileInputStream(file);

        response.setHeader("Cache-Control", "pre-check=0, post-check=0, max-age=0");

        String fileNameKey = "filename";
        if("download".equals(operateType)){
            response.addHeader("Content-Disposition", "attachment; "+fileNameKey+"=\"" + realFileName + "\"");
        }else{
            response.addHeader("Content-Disposition", "inline; "+fileNameKey+"=\"" + realFileName + "\"");
        }

        OutputStream os = response.getOutputStream();
        byte[] buffer = new byte[BUFFER_SIZE];
        try {
            int read;
            while ((read = fis.read(buffer)) != -1) {
                os.write(buffer, 0, read);
            }
        } finally {
            fis.close();
        }
    }

    /**
     post为上传
     **/
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String contentType = request.getContentType();
        try {
            if("application/octet-stream".equals(contentType)){
                storeOctStreamFile(request,response);
            }else if(contentType !=null && contentType.startsWith("multipart/")){
                storeFile(request,response);
            }else{
                throw new RuntimeException("not supported contentType");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new IOException("storeFile异常");
        }
        response.getWriter().write("");
    }

    private void storeOctStreamFile(HttpServletRequest request,
                                           HttpServletResponse response) throws IOException {
        InputStream in = null;
        FileOutputStream storeStream = null;
        try{
            String storeFileName = request.getParameter("storeFileName");

            in = request.getInputStream();
            String storePath = docStorePath ;
            getOrCreateFile(storePath);
            File toStoreFile = new File(storePath + File.separator + storeFileName);
            storeStream = new FileOutputStream(toStoreFile);
            IOUtils.copy(in, storeStream);
        }finally{
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(storeStream);
        }
    }

    private File getOrCreateFile(String path) {
        File storeDir = new File(path);
        if(!(storeDir.exists() && storeDir.isDirectory())){
            storeDir.mkdirs();
        }
        return storeDir;
    }

    public List<FileItem> parseMultipartRequest(HttpServletRequest request) throws FileUploadException {
        DiskFileItemFactory factory = new DiskFileItemFactory();

        ServletContext servletContext = request.getSession().getServletContext();
        File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
        factory.setRepository(repository);

        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);

        // Parse the request
        @SuppressWarnings("unchecked")
        List<FileItem> items = upload.parseRequest(request);
        return items;
    }

    private void storeFile(HttpServletRequest request,
                                  HttpServletResponse response) throws Exception {
        HashMap<String,String> params = new HashMap<String,String>();
        List<FileItem> items =  parseMultipartRequest(request);
        Iterator<FileItem> iter = items.iterator();
        FileItem fileItem = null;
        while (iter.hasNext()) {
            FileItem item = iter.next();
            if (item.isFormField()) {
                String name = item.getFieldName();
                String value = item.getString();
                params.put(name, value);
            } else {
                fileItem = item;
            }
        }
        if(fileItem != null){
            String fileName = params.get("storeFileName");
            File toStoreFile = new File(docStorePath + File.separator + fileName);
            fileItem.write(toStoreFile);
        }

    }
}
